package com.plan.base.util;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;

public class DateUtil {
    public static DateTimeFormatter fmtYearMonthDay = DateTimeFormatter.ofPattern("yyyyMMdd");
    public static final DateTimeFormatter fmtYearMonthDayHourMinuteSecond = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    public static DateTimeFormatter fmtYearMonthDayHourMinuteSecond2 = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
    public static final DateTimeFormatter fmtYearMonthDayHourMinuteSecondNano = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.nnnnnnnnn");


    public static Date stringToDate(String str, DateTimeFormatter format) {
        LocalDateTime dateTime = LocalDateTime.parse(str, format);
        return Date.from(dateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    public static Date parseDate(String yyyyMMdd) {
        LocalDate localDate = LocalDate.parse(yyyyMMdd, fmtYearMonthDay);
        Instant instant = localDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant();
        Date date = Date.from(instant);
        return date;
    }


    public static String formatDateToYearMonthDayHourMinuteSecond(Date date) {
        Instant instant = date.toInstant();
        ZoneId zone = ZoneId.systemDefault();
        LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zone);
        return localDateTime.format(fmtYearMonthDayHourMinuteSecond);
    }

    public static String formatDateToDigitalYearMonthDayHourMinuteSecond(Date date) {
        Instant instant = date.toInstant();
        ZoneId zone = ZoneId.systemDefault();
        LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zone);
        return localDateTime.format(fmtYearMonthDayHourMinuteSecond2);
    }

    public static String formatDateToYearMonthDayHourMinuteSecondNano(Date date) {
        Instant instant = date.toInstant();
        ZoneId zone = ZoneId.systemDefault();
        LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zone);
        return localDateTime.format(fmtYearMonthDayHourMinuteSecondNano);
    }


    public static Date getDateAfterMinutes(int minutes) {
        ZoneId zoneId = ZoneId.systemDefault();
        LocalDateTime localDateTime = LocalDateTime.now();
        LocalDateTime afterMinutes = localDateTime.plusMinutes((long) minutes);
        Instant instant = afterMinutes.atZone(zoneId).toInstant();
        return Date.from(instant);
    }

    public static long getDateAfterSeconds(long seconds) {
        return System.currentTimeMillis() + seconds * 1000L;
    }

    public static Date getDateAfterSeconds2(long seconds) {
        ZoneId zoneId = ZoneId.systemDefault();
        LocalDateTime localDateTime = LocalDateTime.now();
        LocalDateTime afterSeconds = localDateTime.plusSeconds(seconds);
        Instant instant = afterSeconds.atZone(zoneId).toInstant();
        return Date.from(instant);
    }

    public static Date addDays(Date date, int days) {
        Instant instant1 = date.toInstant();
        ZoneId zoneId = ZoneId.systemDefault();
        LocalDateTime localDateTime = instant1.atZone(zoneId).toLocalDateTime();
        LocalDateTime afterDays = localDateTime.plusDays((long) days);
        Instant instant2 = afterDays.atZone(zoneId).toInstant();
        return Date.from(instant2);
    }

    public static Date addSeconds(Date date, int seconds) {
        Instant instant1 = date.toInstant();
        ZoneId zoneId = ZoneId.systemDefault();
        LocalDateTime localDateTime = instant1.atZone(zoneId).toLocalDateTime();
        LocalDateTime afterSeconds = localDateTime.plusSeconds((long) seconds);
        Instant instant2 = afterSeconds.atZone(zoneId).toInstant();
        return Date.from(instant2);
    }

    public static long addSeconds(long now, int seconds) {
        return now + (long) (1000 * seconds);
    }

    public static Date subSeconds(Date date, int seconds) {
        Instant instant1 = date.toInstant();
        ZoneId zoneId = ZoneId.systemDefault();
        LocalDateTime localDateTime = instant1.atZone(zoneId).toLocalDateTime();
        LocalDateTime afterSeconds = localDateTime.minusSeconds((long) seconds);
        Instant instant2 = afterSeconds.atZone(zoneId).toInstant();
        return Date.from(instant2);
    }

    public static int getYearMonthDayFromScheme3Id(long id) {
        long epochMilli = getEpochMilliFromScheme3Id(id);
        return (int) getYearMonthDayFromEpochMilli(epochMilli);
    }

    public static long getYearFromEpochMilli(long epochMilli) {
        LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(epochMilli), ZoneId.systemDefault());
        return (long) localDateTime.getYear();
    }

    public static long getYearMonthFromEpochMilli(long epochMilli) {
        LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(epochMilli), ZoneId.systemDefault());
        int year = localDateTime.getYear();
        int month = localDateTime.getMonthValue();
        return (long) (year * 100 + month);
    }

    public static long getYearMonthDayFromEpochMilli(long epochMilli) {
        LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(epochMilli), ZoneId.systemDefault());
        int year = localDateTime.getYear();
        int month = localDateTime.getMonthValue();
        int day = localDateTime.getDayOfMonth();
        return (long) ((year * 100 + month) * 100 + day);
    }

    public static int getYearMonthDayFromDate(Date date) {
        Instant instant = date.toInstant();
        ZoneId zoneId = ZoneId.systemDefault();
        LocalDateTime localDateTime = instant.atZone(zoneId).toLocalDateTime();
        int year = localDateTime.getYear();
        int month = localDateTime.getMonthValue();
        int day = localDateTime.getDayOfMonth();
        int yearMonthDay = (year * 100 + month) * 100 + day;
        return yearMonthDay;
    }

    public static void getYearMonthDayFromDate(Date date, int[] values) {
        Instant instant = date.toInstant();
        ZoneId zoneId = ZoneId.systemDefault();
        LocalDateTime localDateTime = instant.atZone(zoneId).toLocalDateTime();
        int year = localDateTime.getYear();
        int month = localDateTime.getMonthValue();
        int day = localDateTime.getDayOfMonth();
        values[0] = year;
        values[1] = month;
        values[2] = day;
    }

    public static boolean isSameWeek(Date beginTime, Date endTime) {
        ZoneId zoneId = ZoneId.systemDefault();
        Instant beginInstant = beginTime.toInstant();
        LocalDateTime beginLocalDateTime = beginInstant.atZone(zoneId).toLocalDateTime();
        Instant endInstant = endTime.toInstant();
        LocalDateTime endLocalDateTime = endInstant.atZone(zoneId).toLocalDateTime();
        int rang = endLocalDateTime.getDayOfYear() - beginLocalDateTime.getDayOfYear();
        return rang <= 6;
    }


    public static LocalDate dateToLocalDate(Date date) {
        return Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault()).toLocalDate();
    }

    public static Date localDateTimeToDate(LocalDateTime localDateTime) {
        ZoneId zone = ZoneId.systemDefault();
        Instant instant = localDateTime.atZone(zone).toInstant();
        return Date.from(instant);
    }

    public static Date getToadyMaxTime() {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime zero = LocalDateTime.of(now.getYear(), now.getMonth(), now.getDayOfMonth(), 23, 59, 59, 999999999);
        ZoneId zone = ZoneId.systemDefault();
        Instant instant = zero.atZone(zone).toInstant();
        return Date.from(instant);
    }

    public static String formatDateToYearMonthDay(Date date) {
        Instant instant = date.toInstant();
        ZoneId zone = ZoneId.systemDefault();
        LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zone);
        return localDateTime.format(fmtYearMonthDay);
    }

    public static String yearMonthDayToDateString(int yyyyMMdd) {
        // 将int转换为字符串
        String dateStr = String.valueOf(yyyyMMdd);

        // 检查输入长度是否正确
        if (dateStr.length() != 8) {
            throw new IllegalArgumentException("输入的日期格式不正确，应为8位数字");
        }
        // 使用String.format进行格式化
        return String.format("%s-%s-%s", dateStr.substring(0, 4), dateStr.substring(4, 6), dateStr.substring(6, 8));
    }


    public static LocalDate convertToIntToLocalDate(int yyyyMMdd) {
        // 检查输入是否为8位数字
        if (yyyyMMdd < 10000000 || yyyyMMdd > 99999999) {
            throw new IllegalArgumentException("输入的日期格式不正确，应为8位数字");
        }

        // 提取年、月、日
        int year = yyyyMMdd / 10000;
        int month = (yyyyMMdd % 10000) / 100;
        int day = yyyyMMdd % 100;

        // 创建LocalDate对象
        return LocalDate.of(year, month, day);
    }

    public static String getChineseWeekday(int yyyyMMdd) {
        LocalDate localDate = convertToIntToLocalDate(yyyyMMdd);
        return getChineseWeekday(localDate.getDayOfWeek());
    }

    public static String getChineseWeekday(Date day) {
        // 使用 Calendar 获取星期几
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(day);
        int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);

        // 将 Calendar 的 DAY_OF_WEEK 映射到中文星期
        switch (dayOfWeek) {
            case Calendar.SUNDAY:
                return "星期日";
            case Calendar.MONDAY:
                return "星期一";
            case Calendar.TUESDAY:
                return "星期二";
            case Calendar.WEDNESDAY:
                return "星期三";
            case Calendar.THURSDAY:
                return "星期四";
            case Calendar.FRIDAY:
                return "星期五";
            case Calendar.SATURDAY:
                return "星期六";
            default:
                throw new IllegalArgumentException("Invalid day of week: " + dayOfWeek);
        }
    }


    private static String getChineseWeekday(DayOfWeek dayOfWeek) {
        switch (dayOfWeek) {
            case MONDAY:
                return "星期一";
            case TUESDAY:
                return "星期二";
            case WEDNESDAY:
                return "星期三";
            case THURSDAY:
                return "星期四";
            case FRIDAY:
                return "星期五";
            case SATURDAY:
                return "星期六";
            case SUNDAY:
                return "星期日";
            default:
                throw new IllegalArgumentException("未知的星期几");
        }
    }

    private static long getEpochMilliFromScheme3Id(long id) {
        return (id >> 21) + 1640966400000L;
    }

}
